package com.basker.pisces.domain.validation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.basker.pisces.domain.validation.validator.IValidator;
import com.basker.pisces.service.exception.IObjectErrorsWrapper.ObjectError;

/**
 * 验证器返回的结果
 *
 * @author hangwen
 * @see IValidator
 */
public class ValidationErrors {
    public static final ValidationErrors NO_ERROR = new NoError();
    private static final String NO_ERROR_MESSAGE = "NO ERROR";
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    private List<ObjectError> errors = new ArrayList<>();

    public void addError(ObjectError error) {
        Assert.notNull(error, "parameter 'error' is required");

        this.errors.add(error);
    }

    public void addErrors(Collection<ObjectError> errors) {
        if (CollectionUtils.isEmpty(errors)) {
            return;
        }

        this.errors.addAll(errors);
    }

    /**
     * 从objects过滤出有效的业务对象
     *
     * @param dataObjects
     * @return
     */
    public List<Object> filterValidObjects(List<Object> dataObjects) {
        if (!this.hasError()) {
            return dataObjects;
        }

        return ValidationErrorsUtils.filterValidObjects(dataObjects, getErrorObjects());
    }

    /**
     * 获取有错误的业务对象
     *
     * @return
     */
    public List<Object> getErrorObjects() {
        if (!this.hasError()) {
            return Collections.emptyList();
        }

        return ValidationErrorsUtils.getErrorObjects(this.errors);
    }

    /**
     * 获取所有错误
     *
     * @return
     */
    public List<ObjectError> getErrors() {
        return errors;
    }

    public void setErrors(List<ObjectError> errors) {
        this.errors = errors;
    }

    /**
     * 获取errorObject的错误
     *
     * @param errorObject
     * @return
     */
    public List<ObjectError> getErrors(Object errorObject) {
        Assert.notNull(errorObject, "parameter 'errorObject' is required");

        if (!this.hasError()) {
            return Collections.emptyList();
        }

        return ValidationErrorsUtils.getErrors(this.errors, errorObject);
    }

    /**
     * 获取所有IValidationObjectError类型的错误
     *
     * @return
     */
    public List<IValidationObjectError<?>> getValidationErrors() {
        if (!this.hasError()) {
            return Collections.emptyList();
        }

        return this.errors.stream().filter(e -> e instanceof IValidationObjectError<?>)
                .map(e -> (IValidationObjectError<?>) e).collect(Collectors.toList());
    }

    public boolean hasError() {
        return !CollectionUtils.isEmpty(this.errors);
    }

    public void merge(ValidationErrors other) {
        if (other == null || CollectionUtils.isEmpty(other.errors)) {
            return;
        }

        this.errors.addAll(other.errors);
    }

    @Override
    public String toString() {
        if (!this.hasError()) {
            return NO_ERROR_MESSAGE;
        }

        // 将所有异常的消息串联起来
        String[] messages = this.errors.stream().map(e -> e.getErrorMessage()).toArray(s -> new String[s]);
        return String.join("," + LINE_SEPARATOR, messages);
    }

    private static final class NoError extends ValidationErrors {
        @Override
        public void addError(ObjectError error) {

        }

        @Override
        public List<ObjectError> getErrors() {
            return Collections.emptyList();
        }

        @Override
        public void setErrors(List<ObjectError> errors) {

        }

        @Override
        public boolean hasError() {
            return false;
        }

        @Override
        public void merge(ValidationErrors other) {

        }
    }
}
